//
//  VVGridTiledView.m
//  Masonry
//
//  Created by xiaerfei on 2019/1/2.
//

#import "VVGridTiledView.h"
#import "VVViewContainer.h"
#import "VVTemplateManager.h"
#import "VVPropertyExpressionSetter.h"

@interface VVGridTiledView()

@property (nonatomic, weak) id lastData;

@end

@implementation VVGridTiledView
@synthesize rootCocoaView = _rootCocoaView, rootCanvasLayer = _rootCanvasLayer;

- (instancetype)init
{
    if (self = [super init]) {
        _lastData = self;
    }
    return self;
}

- (void)setRootCocoaView:(UIView *)rootCocoaView
{
    _rootCocoaView = rootCocoaView;
    if (self.cocoaView.superview !=  rootCocoaView) {
        if (self.cocoaView.superview) {
            [self.cocoaView removeFromSuperview];
        }
        [rootCocoaView addSubview:self.cocoaView];
    }
}

- (void)setRootCanvasLayer:(CALayer *)rootCanvasLayer
{
    _rootCanvasLayer = rootCanvasLayer;
    if (self.canvasLayer) {
        if (self.canvasLayer.superlayer) {
            [self.canvasLayer removeFromSuperlayer];
        }
        [rootCanvasLayer addSublayer:self.canvasLayer];
    }
}

- (BOOL)setDataObj:(NSObject *)obj forKey:(int)key
{
    if (key == STR_ID_dataTag) {
        if (obj != _lastData && [obj isKindOfClass:[NSArray class]]) {
            _lastData = obj;
            
            NSMutableArray *unusedNodes = [self.subNodes mutableCopy]; // for reusing feature
            NSArray *dataArray = (NSArray *)obj;
            for (NSDictionary *itemData in dataArray) {
                if ([itemData isKindOfClass:[NSDictionary class]] == NO
                    || [itemData.allKeys containsObject:@"type"] == NO) {
                    continue;
                }
                NSString *nodeType = [itemData objectForKey:@"type"];
                VVBaseNode *node = [VVGridTiledView popReuseableNodeWithType:nodeType fromUnusedNodes:unusedNodes];
                if (!node) {
                    node = [[VVTemplateManager sharedManager] createNodeTreeForType:nodeType];
                }
                NSArray *variableNodes = [VVViewContainer variableNodes:node];
                for (VVBaseNode *variableNode in variableNodes) {
                    [variableNode reset];
                    
                    for (VVPropertyExpressionSetter *setter in variableNode.expressionSetters.allValues) {
                        if ([setter isKindOfClass:[VVPropertyExpressionSetter class]]) {
                            [setter applyToNode:variableNode withObject:itemData];
                        }
                    }
                    variableNode.actionValue = [itemData objectForKey:variableNode.action];
                    
                    [variableNode didUpdated];
                }
                if (node.superNode == nil) {
                    [self addSubNode:node];
                    node.rootCanvasLayer = self.cocoaView.layer;
                    node.rootCocoaView = self.cocoaView;
                }
            }
            for (VVBaseNode *unusedNode in unusedNodes) {
                [unusedNode removeFromSuperNode];
                unusedNode.rootCanvasLayer = nil;
                unusedNode.rootCocoaView = nil;
            }
        }
        return YES;
    }
    return NO;
}

- (void)layoutSubNodes {
    CGSize contentSize = self.contentSize;

    CGSize gridSizeWithMargin = CGSizeMake((contentSize.width + self.itemHorizontalMargin) / self.subNodes.count,
                                           (contentSize.height + self.itemVerticalMargin) / 1);
    CGSize gridSize = CGSizeMake(gridSizeWithMargin.width - self.itemHorizontalMargin,
                                 gridSizeWithMargin.height - self.itemVerticalMargin);
    int index = 0, col, row;
    
    for (VVBaseNode *subNode in self.subNodes) {
        if (subNode.visibility == VVVisibilityGone) {
            [subNode updateHiddenRecursively];
            continue;
        }
        CGSize subNodeSize = [subNode calculateSize:gridSize];
        if ([subNode needLayout]) {
            col = index % self.subNodes.count;
            row = index / self.subNodes.count;
            
            if (subNode.layoutGravity & VVGravityHCenter) {
                CGFloat midX = self.paddingLeft + gridSizeWithMargin.width * (col + 0.5);
                subNode.nodeX = midX - subNodeSize.width / 2;
            } else if (subNode.layoutGravity & VVGravityRight) {
                subNode.nodeX = self.paddingLeft + gridSizeWithMargin.width * (col + 1) - self.itemHorizontalMargin - subNode.marginRight - subNodeSize.width;
            } else {
                subNode.nodeX = self.paddingLeft + gridSizeWithMargin.width * col + subNode.marginLeft;
            }
            
            if (subNode.layoutGravity & VVGravityVCenter) {
                CGFloat midY = self.paddingTop + gridSizeWithMargin.height * (row + 0.5);
                subNode.nodeY = midY - subNodeSize.height / 2;
            } else if (subNode.layoutGravity & VVGravityBottom) {
                subNode.nodeY = self.paddingTop + gridSizeWithMargin.height * (row + 1) - self.itemVerticalMargin - subNode.marginBottom - subNodeSize.height;
            } else {
                subNode.nodeY = self.paddingTop + gridSizeWithMargin.height * row + subNode.marginTop;
            }
        }
        [subNode updateHidden];
        [subNode updateFrame];
        [subNode layoutSubNodes];
        index++;
    }
}




+ (VVBaseNode *)popReuseableNodeWithType:(NSString *)nodeType fromUnusedNodes:(NSMutableArray *)unusedNodes
{
    VVBaseNode *reuseableNode = nil;
    for (VVBaseNode *unusedNode in unusedNodes) {
        if ([unusedNode.templateType isEqualToString:nodeType]) {
            reuseableNode = unusedNode;
            break;
        }
    }
    if (reuseableNode) {
        [unusedNodes removeObject:reuseableNode];
    }
    return reuseableNode;
}

@end
